#include <stdio.h>
#include <string.h>
#include "uart.h"

#define MAX_UART_NUM 1
static uart_t serial_list[MAX_UART_NUM];
static int8_t cur_cnt = 0;

void user_uart_irq_handler(UART_HandleTypeDef *huart, uint16_t data_length)
{
    for (int8_t i = 0; i < cur_cnt; i++)
    {
        if (serial_list[i].uart_handle == huart)
        {
            HAL_UART_DMAStop(huart); // 停止本次DMA传输

            if (serial_list[i].recv_cb)
            {
                serial_list[i].dma_buff[data_length] = '\0';
                serial_list[i].recv_cb(serial_list[i].dma_buff, data_length, serial_list[i].user_data);
            }
            memset(serial_list[i].dma_buff, 0, data_length); // 清零接收缓冲区

            // HAL_UART_Receive_DMA(serial_list[i].uart_handle, serial_list[i].dma_buff, serial_list[i].dma_buf_len); // 重启开始DMA传输 每次255字节数据
            HAL_UARTEx_ReceiveToIdle_DMA(serial_list[i].uart_handle, serial_list[i].dma_buff, serial_list[i].dma_buf_len); // 重启开始DMA传输 每次255字节数据
        }
    }
}

/*if wanna to use the below irq handler,must use the HAL_UARTEx_ReceiveToIdle_DMA function*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    user_uart_irq_handler(huart, Size);
}

HAL_StatusTypeDef uart_recv_register(serial_config_t *config)
{
    if (cur_cnt >= MAX_UART_NUM)
    {
        serial_send("error: uart num overflow");
        return HAL_ERROR;
    }

    serial_list[cur_cnt].uart_handle = config->uart_handle;
    serial_list[cur_cnt].recv_cb = config->recv_cb;
    serial_list[cur_cnt].user_data = config->user_data;
    serial_list[cur_cnt].dma_buf_len = config->dma_buf_len;
    serial_list[cur_cnt].dma_buff = config->dma_buff;

    __HAL_UART_ENABLE_IT(config->uart_handle, UART_IT_IDLE);
    // HAL_UART_Receive_DMA(serial_list[cur_cnt].uart_handle, serial_list[cur_cnt].dma_buff, serial_list[cur_cnt].dma_buf_len);
    HAL_UARTEx_ReceiveToIdle_DMA(serial_list[cur_cnt].uart_handle, serial_list[cur_cnt].dma_buff, serial_list[cur_cnt].dma_buf_len);
    cur_cnt++;
    return HAL_OK;
}

// declare the extern variables
HAL_StatusTypeDef serial_init(serial_recv_cb_t recv_cb, void *user_data)
{
    serial_config_t uart_config;
    extern UART_HandleTypeDef huart1;
    uart_config.uart_handle = &huart1;
    uart_config.recv_cb = recv_cb;
    uart_config.user_data = user_data;

    uart_config.dma_buf_len = 512;
    static uint8_t dma_buff[512];
    uart_config.dma_buff = dma_buff;

    return uart_recv_register(&uart_config);
}
void serial_send_with_len(const char *str, uint16_t len)
{
    extern UART_HandleTypeDef huart1;
    HAL_UART_Transmit(&huart1, (const uint8_t *)str, len, 0xffff);
}
void serial_send(const char *str)
{
    serial_send_with_len(str, strlen(str));
}
void serial_send_char(char ch)
{
    extern UART_HandleTypeDef huart1;
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); // 阻塞方式打印,串口1
}

/*use the printf to send the char*/
// #ifdef __GNUC__
// #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
// #else
// #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
// #endif
// PUTCHAR_PROTOTYPE
// {
//     HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); // 阻塞方式打印,串口1
//     return ch;
// }